package ScalaStudy.chapter05

object Test05_Lambda {
  def main(args: Array[String]): Unit = {


    /////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////   匿名函数   /////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////////////////


    //（1）匿名函数的应用**************************************************************

println("(1)")

    val f1 = (name: String) => { println(name) }                     //f1为匿名函数
    f1("wq1")

    //（2）定义一个函数，以函数作为参数输入************************************************

println("(2)")

    def f2 (func: String => Unit) : Unit =                          //fun为函数类型
    {
      func("wq2")                                                   //这里的func调用也就是调用f1表达式
    }

    f2(f1)                                                          //func = f1
    f2((name: String) => { println(name) })

    //匿名函数的简化原则
//    （3）	参数的类型可以省略，会根据形参进行自动的推导
println("(3)")

    f2((name) => {
      println(name) }
    )

//    （4）	类型省略之后，发现只有一个参数，则圆括号可以省略；其他情况：没有参数和参数超过 1 的永远不能省略圆括号。
println("(4)")

    f2(name => {
      println(name) }
    )

//    （5）	匿名函数如果只有一行，则大括号也可以省略
println("(5)")
    f2( name => println(name) )

//    （6）	如果参数只出现一次，则参数省略且后面参数可以用_代替
println("(6)")
    f2( println(_) )

//    （7）	如果可以推断出，println是一个函数体，不是调用语句，可以省略下划线
println("(7)")
    f2( println )


    /////////////////////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////   实际示例   /////////////////////////////////////
    /////////////////////////////////////////////////////////////////////////////////////////


    //（8）定义一个“二元函数”，只操作1和2两个数，但是具体参数通过参数传入
println("(8)")

    def dualFunctionOneAndTwo(fun: (Int,Int) => Int) : Int = {
      fun(1,2)
    }

    val add = (a: Int, b: Int) => {a + b}
    val sub = (a: Int, b: Int) => {a - b}
    println(dualFunctionOneAndTwo(add))
    println(dualFunctionOneAndTwo(sub))

    //匿名函数简化
    println(dualFunctionOneAndTwo( (a: Int, b: Int) => {a + b}) )
    println(dualFunctionOneAndTwo( (a: Int, b: Int) => {a - b}) )

    println(dualFunctionOneAndTwo( (a, b) => a + b) )
    println(dualFunctionOneAndTwo(_ + _) )

  }
}
